package drds.plus.sql_process.type.impl;

import drds.plus.common.model.RowValues;
import drds.plus.common.utils.convertor.Convertor;
import drds.plus.sql_process.type.*;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.util.Calendar;

/**
 * {@link Time}类型
 */
public class TimeType extends AbstractType<Time> {

    private static final Time maxTime = Time.valueOf("23:59:59");
    private static final Time minTime = Time.valueOf("00:00:00");
    private final Calculator calculator = new AbstractCalculator() {

        public Object doAdd(Object v1, Object v2) {
            Calendar cal = Calendar.getInstance();
            if (v1 instanceof IntervalType) {
                Time i2 = convert(v2);
                cal.setTime(i2);
                ((IntervalType) v1).process(cal, 1);
            } else if (v2 instanceof IntervalType) {
                Time i1 = convert(v1);
                cal.setTime(i1);
                ((IntervalType) v2).process(cal, 1);
            } else {
                throw new UnsupportedOperationException("时间类型不支持算术符操作");
            }

            return convert(cal.getTime());
        }

        public Object doSub(Object v1, Object v2) {
            Calendar cal = Calendar.getInstance();
            if (v1 instanceof IntervalType) {
                Time i2 = convert(v2);
                cal.setTime(i2);
                ((IntervalType) v1).process(cal, -1);
            } else if (v2 instanceof IntervalType) {
                Time i1 = convert(v1);
                cal.setTime(i1);
                ((IntervalType) v2).process(cal, -1);
            } else {
                throw new UnsupportedOperationException("时间类型不支持算术符操作");
            }

            return convert(cal.getTime());
        }

        public Object doMultiply(Object v1, Object v2) {
            throw new UnsupportedOperationException("时间类型不支持算术符操作");
        }

        public Object doDivide(Object v1, Object v2) {
            throw new UnsupportedOperationException("时间类型不支持算术符操作");
        }

        public Object doMod(Object v1, Object v2) {
            throw new UnsupportedOperationException("时间类型不支持算术符操作");
        }

    };
    private Convertor longToDate = null;

    public TimeType() {
        longToDate = this.getConvertor(Long.class);
    }

    public ResultGetter getResultGetter() {
        return new ResultGetter() {

            public Object get(ResultSet resultSet, int index) throws SQLException {
                return resultSet.getTime(index);
            }

            public Object get(RowValues rowValues, int index) {
                Object val = rowValues.getObject(index);
                return convert(val);
            }
        };
    }

    public int encode(Object value, byte[] bytes, int offset) {
        return Encoder.encode(LongType.convert(value), bytes, offset);
    }

    public int getLength(Object value) {
        if (value == null) {
            return 1;
        } else {
            return 9;
        }
    }

    public DecodeResult decode(byte[] bytes, int offset) {
        Long v = Decoder.decodeLongObject(bytes, offset);
        if (v == null) {
            return new DecodeResult(null, getLength(v));
        } else {
            Time date = (Time) longToDate.convert(v, getValueClass());
            return new DecodeResult(date, getLength(v));
        }
    }

    public Time incr(Object value) {
        return new Time(((Time) value).getTime() + 1l);
    }

    public Time decr(Object value) {
        return new Time(((Time) value).getTime() - 1l);
    }

    public Time getMaxValue() {
        return maxTime;
    }

    public Time getMinValue() {
        return minTime;
    }

    public int compare(Object o1, Object o2) {
        if (o1 == o2) {
            return 0;
        }
        if (o1 == null) {
            return -1;
        }

        if (o2 == null) {
            return 1;
        }

        Time d1 = convert(o1);
        Time d2 = convert(o2);
        return d1.compareTo(d2);
    }

    public Calculator getCalculator() {
        return calculator;
    }

    public int getSqlType() {
        return java.sql.Types.TIME;
    }
}
